/* hash table */


#include "hashtable.h"
/* modify these lines to establish data type */


#define compEQ(a,b) (a == b)

typedef struct Node_ {
    struct Node_ *next;         /* next node */
    int port;                   /* port number stored in node */
	char* protocol;             /* protocol name stored in node */
} Node;

typedef struct hashTable_t
{
	Node** head;
	int hashTableSize;
}_hashTable;

typedef int hashTableIndex;

hashTableIndex hash(int port, int hashTableSize) {

   /***********************************
    *  hash function applied to data  *
    ***********************************/

    return (port % hashTableSize);
}

void insertRule(hashTable hashT, int port, char* protocol) {
    Node *p, *p0;
    hashTableIndex bucket;
	_hashTable hT = *hashT;	
   /************************************************
    *  allocate node for data and insert in table  *
    ************************************************/

    /* insert node at beginning of list */
    bucket = hash(port, hT.hashTableSize);
    if ((p = malloc(sizeof(Node))) == 0) {
        /*fprintf (stderr, "out of memory (hashTable)\n");
        exit(1);*/
		return;
    }
    p0 = hT.head[bucket];
    hT.head[bucket] = p;
    p->next = p0;
    p->port = port;
	p->protocol = protocol;
    return ;
}


char* findProtocol(hashTable hashT, int port) {
    Node *p;
    _hashTable hT = *hashT;	
   /*******************************
    *  find node containing data  *
    *******************************/

    p = hT.head[hash(port, hT.hashTableSize)];
    while (p && !compEQ(p->port, port)) 
        p = p->next;
    return p->protocol;
}


hashTable createHashTable(int _hashTableSize)
{
    
	hashTable hT;
	Node ** head;
    if ((head = (Node**)malloc(_hashTableSize * sizeof(Node *))) == 0) {
        /*fprintf (stderr, "out of memory (hashTable)\n");
        exit(1);*/
		return NULL;
    }

	if((hT = (hashTable)malloc(sizeof(_hashTable))) == 0) {
        /*fprintf (stderr, "out of memory (hashTable)\n");
        exit(1);*/
		return NULL;
    }

	hT->hashTableSize = _hashTableSize;
	hT->head = head;
	return hT;
	
}

void destroyBucket(Node * head)
{
	Node* tmpNext;

	if(!head)
		return;
    
	/*destroy each node in the list*/ 
	while (head->next)
	{
		tmpNext=head->next->next;
		free(head->next);
		head->next=tmpNext;	
	}	
		
	return;
}
	
void destroyHash(hashTable hashT)
{
	int size = hashT->hashTableSize;
	int i;
	for (i = 0; i < size; ++i)
	{
		destroyBucket((hashT->head)[i]);
	}

	free(hashT);
}


